function JForm(owner, parent, name, caption, action, method, rect, flags, previous, reports, modal)
{
	var self = this,
	_rendered = false,
	_disposed = false,
	_isResizing = false,
	_resizeTimer = null,
	_delayedResize = false;

	this.initialize(owner, parent, name, caption, action, rect, flags);

	this.set_visible = set_visible;

	this.activeControl = null;
	this.isForm   = true;
	this.method   = method;
	this.previous = previous;
	this.reports  = reports;
	this.modal    = modal;
	this.nextModal = null;
	this.methods  = (cmRender | cmLoad);

	this.checkSaveButton = checkSaveButton;
	this.setSaveButton = setSaveButton;
	this.close  = close;
	this.dispose = dispose;
	this.isRendered = isRendered;
	this.load   = load;
	this.loaded = false;
	this.render = render;
	this.navigateDataset = navigateDataset;
	this.refreshData = refreshData;
	this.saveData = saveData;
	this.setActive = setActive;
	this.setActiveControl = setActiveControl;
	this.set_caption = setCaption;

	this.ondispose = new JEvent();
	this.onload = new JEvent();
	this.onresize = new JEvent();
	this.onvisibilitychanged = new JEvent();

	this.owner.addImage("close-icon", "close.gif", "form");
	this.owner.activeForm = this;

	if ((this.modal == 'prev') && (this.previous != '') && (this.owner.getObject(this.previous) != null))
	{
		self.owner.getObject(this.previous).nextModal = this.name;
	}


	function render(fs, force)
	{
		if (_rendered && !force)
			return;

		fs.append('<div id="' + self.name + '" class="form">');
		fs.append('  <div id="' + self.name + '_title" class="form_titlebar">');
		fs.append('    <span id="' + self.name + '_caption" class="form_caption">' + self.caption + '</span>');
		fs.append('    <span id="' + self.name + '_recCount" class="form_recCount"></span>');
		fs.append('    <img id="' + self.name + '_closeicon" class="form_bordericon" alt="' + hiCloseIcon + '">');
		fs.append('  </div>');

		fs.append('  <div id="' + self.name + '_toolbar"></div>');
		fs.append('  <div class="form_body" id="' + self.name + '_content">');
		self.controls.forEach( function (control)
		{
			if ((utils.inSet(cmRender, control.methods)) && (control.constructor != JButton))
			{
				control.render(fs);
			}
		}, self);
		fs.append('  </div>');

		fs.append('  <div class="form_buttons" id="' + self.name + '_buttons">');

		var buttons = [];
		self.controls.forEach( function (control)
		{
			if (control.constructor == JButton)
			{
				control.mainFormButton = true;
				buttons.push(control);
			}
		}, self);

		buttons.sort(sortFunction);
		buttons.forEach( function (button)
		{
			button.render(fs);
			fs.append('<br/>');
		}, self);
		buttons = null;
		
		fs.append('  </div>');

		fs.append('<div class="clearFloat"></div></div>');

		_rendered = true;
	}


	function load()
	{
		var elem = self.$$('_closeicon');
		elem.src = self.owner.images["close-icon"].src;
		elem.onclick = self.close;

		_setSize(true);

		self.controls.forEach(function(control)
		{
			if (utils.inSet(cmLoad, control.methods))
			{
				control.load();
			}
		}, self);

		self.setActiveControl(self.activeControl);

		self.owner.onresize.attach(_onresize);
        _onresize();

		self.onload.raise(self, self);
		self.loaded = true;
	}

	function _setSize(noResizeRaise)
	{
		if (_disposed)
			return;

		if (self.owner.activeForm != self)
		{
			_clearResizing();
			_delayedResize = true;
			return;
		}

		var mainH = self.$$().parentNode.clientHeight;
		var mainW = self.$$().parentNode.clientWidth;
		self.$$().style.height = mainH - 20; 
		self.$$().style.width =  mainW - 20; 
		var content = self.$$('_content');
		var w = mainW - self.$$('_buttons').clientWidth - 40;
		if (w < 10)
			w = 10;
		var h = mainH - 40;
		if (h < 10)
			h = 10;

//		if (w != content.clientWidth) 
			content.style.width = w;  

//		if (h != content.clientHeight) 
			content.style.height = h

		self.owner.getWindow().setTimeout(_clearResizing, 10);

		if (noResizeRaise != true)
		{
			self.onresize.raise();

			if (!browser.isIE)
			{
				_setSize(true);
			}
		} 
	}

	function _clearResizing()
	{
		_isResizing = false;
		_resizeTimer = null;
	}

	function _onresize()
	{
		if ((_isResizing) || (_resizeTimer != null))
			return;

		_isResizing = true;
		_resizeTimer = self.owner.getWindow().setTimeout(_setSize, 100);
	}

	function sortFunction(item1, item2)
	{
		if (item1.tabIndex > item2.tabIndex)
			return 1;
		else
		if (item1.tabIndex < item2.tabIndex)
			return -1;
		else
			return 0;
	} 

	function isRendered()
	{
		return _rendered;
	}

	function refreshData()
	{
		if ((self.dataset.isMemVars()) || (self.dataset.isLocal))
			return;

		self.owner.post(raCleanup, null);
	}

	function navigateDataset(action)
	{
		if ((self.dataset.isMemVars()) || (self.dataset.isLocal))
			return;

		switch (action)
		{
			case 'NavFirstPage':
				self.dataset.moveToPage(0);
				break;
			case 'NavPrevPage':
				self.dataset.moveToPage(-1, true);
				break;
			case 'NavPrevRec':
				self.dataset.movePrev();
				break;
			case 'NavNextRec':
				self.dataset.moveNext();
				break;
			case 'NavNextPage':
				self.dataset.moveToPage(1, true);
				break;
			case 'NavLastPage':
				self.dataset.moveToPage(maxInt);
				break;
		}
	}

	function saveData()
	{
		self.datasets.forEach( function (ds)
		{
			ds.saveAll();
		}, self);
	}

	function setActive(active)
	{
	}

	function setCaption(caption)
	{
		self.caption = caption;

		if (self.$$('_caption') != null)
		{
			self.$$('_caption').innerHTML = caption;
			self.owner.fillFormsList(true);
		}
	}

	function setActiveControl(control)
	{
		self.activeControl = control;
		if (control && control.setFocus)
			control.setFocus();
		var filtering = true;
		var refresh = true;
		var searching = true;
		var sorting = true;
		var dsReadOnly = false;
		var inserting = true;

		if (((control == null) || (control.dataset == null)) && (self.$$('_recCount') != null))
		{
			self.$$('_recCount').innerHTML = '';
		}

		if ((control != null) && (control.dataset != null))
		{
			dsReadOnly = control.dataset.isReadOnly();
			if ((self.dataset.isMemVars()) || (self.dataset.fields.length == 0))
			{
				filtering = false;
				refresh = false;
				searching = false;
				sorting = false;
			}
			else
			{
				sorting = (! utils.inSet(dfNoSort, control.dataset.flags));
				filtering = (! utils.inSet(dfNoFilter, control.dataset.flags));
				inserting = (! utils.inSet(dfNoInsert, control.dataset.flags));
			}

			if (self.$$('_recCount') != null)
				self.$$('_recCount').innerHTML = control.dataset.getRealRecCount();
		}
		else
		if (self.dataset != null)
		{
			dsReadOnly = self.dataset.isReadOnly();
			if ((self.dataset.isMemVars()) || (self.dataset.fields.length == 0))
			{
				filtering = false;
				refresh = false;
				searching = false;
				sorting = false;
			}
			else
			{
				sorting = (! utils.inSet(dfNoSort, self.dataset.flags));
				filtering = (! utils.inSet(dfNoFilter, self.dataset.flags));
				inserting = (!utils.inSet(dfNoInsert, self.dataset.flags));
			}
		}

		if (self.owner.toolbar != null)
		{
			if (self.owner.toolbar.setFiltering)
				self.owner.toolbar.setFiltering(filtering);
			if (self.owner.toolbar.setRefresh)
				self.owner.toolbar.setRefresh(refresh);
			if (self.owner.toolbar.setSearching)
				self.owner.toolbar.setSearching(searching);
			if (self.owner.toolbar.setSorting)
				self.owner.toolbar.setSorting(sorting);
			if (self.owner.toolbar.setPrinting)
				self.owner.toolbar.setPrinting(!utils.isEmpty(self.reports));
			if (self.owner.toolbar.setInserting)
				self.owner.toolbar.setInserting(inserting);
			if (self.owner.toolbar.setRecordOperations)
				self.owner.toolbar.setRecordOperations(!dsReadOnly);
		}

		checkSaveButton();
	}

	function checkSaveButton(control)
	{
		var save = false;
		var ctrl = (control == null) ? self.activeControl : control;

		if (ctrl != null)
		{
			if ((ctrl.isDirty) && (ctrl.isDirty() === true))
				save = true;
			else
			if (ctrl.dataset != null)
				save = ctrl.dataset.isDirty(true);
		}
		else
		if ((self.dataset != null) && (!self.dataset.isMemVars()))
			save = self.dataset.isDirty(true);

		if ((self.owner.toolbar != null) && (self.owner.toolbar.setSave))
			setSaveButton(save);
	}

	function setSaveButton(value)
	{
			self.owner.toolbar.setSave(value);
	}

	function _checkDSSync()
	{
		self.datasets.forEach( function(ds)
		{
			if (ds.checkSync)
				ds.checkSync();
		}, self); 
	}

	function _checkDSState()
	{
		self.datasets.forEach( function(ds)
		{
			if ((!ds.isLocal) && (ds.isDirty()) && (self.owner.askForSaving(self)))
			{
				ds.saveAll();
			}
		}, self); 
	}


	function set_visible(value)
	{
		self.base.set_visible.call(self, value);
		if (value)
		{
			self.owner.set_activeForm(self.name);
			_checkDSSync();
			self.setActiveControl(self.activeControl);

			if (_delayedResize)
				_onresize();
		}
	}

	function close(event, cleaning)
	{
		_checkDSState();

		var query = new Postback();
		query.set("obj", self.name);

		if (cleaning)
			self.owner.post(raCloseForm, query, true, /*true*/false);
		else
			self.owner.post(raCloseForm, query, false, /*true*/false);
	}

	function dispose()
	{
		if (_disposed)
			return;

		var elem = self.$$();

		if (elem != null)
            self.owner.onresize.detach(_onresize);

		self.ondispose.raise(self, self);

		self.onresize.dispose();
		self.onresize = null;
		self.ondispose.dispose();
		self.ondispose = null;
		self.onload.dispose();
		self.onload = null;
		self.loaded = false;

		self.disposeChildren();

		if (elem != null)
		{
			elem.onclick = null;
			if (elem.parentNode != null)
				elem.parentNode.removeChild(elem);

			delete elem;
		}

		if ((self.previous != '') && (self.owner.getObject(self.previous) != null) && (self.owner.getObject(self.previous).nextModal == self.name))
		{
			self.owner.getObject(this.previous).nextModal = null;
		}

		this.activeControl = null;
		self.owner._debugShow(true);

		self.base.dispose.call(self);

		_disposed = true;
	}

}

JForm.inheritsFrom(ControlBase);

if (typeof(loadNextScript) != 'undefined')
	loadNextScript();
